//
//  Episode.swift
//  WBDemo
//
//  Created by Jin on 25/04/2018.
//  Copyright © 2018 com.baidu.123. All rights reserved.
//

import Foundation

struct EpisodeGeneral:Codable {
    
    var expiresIn:Int32
    var accessToken:String
    var remindIn:String
    var isRealName:String
    var uid:String
    var createdAt:Date
    var duration:Float
    var origin:Data
    var url:URL
    var type:EpisodeType
    var comment:String?//处理optional时,如果为nil,系统默认不会出现在结果里
    var slices:[Float] //自定义数组编码,将之转换为百分比
    
    //是否付费
    enum EpisodeType:String,Codable {
        case free
        case paid
    }
    
    //自定义映射规则,适用于服务器数据与模型不一致情况,例如:服务器返回expires_in -> 模型expiresIn
    enum CodingKeys:String,CodingKey {
        case expiresIn = "expires_in"
        case accessToken = "access_token"
        case remindIn = "remind_in"
        case isRealName
        case uid
        case createdAt = "created_at"
        case origin
        case url
        case type
        case comment
        case meta
    }
    
    //自定义meta映射规则
    enum MetaCodingKeys:String,CodingKey {
        case duration
        case slices
    }
    
    
    //自定义解码json需要实现下面两个init方法
    init(from decoder:Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        let accessToken = try container.decode(String.self, forKey: .accessToken)
        let expiresIn = try container.decode(Int32.self, forKey: .expiresIn)
        let remindIn = try container.decode(String.self, forKey: .remindIn)
        let isRealName = try container.decode(String.self, forKey: .isRealName)
        let uid = try container.decode(String.self, forKey: .uid)
        let type = try container.decode(EpisodeType.self, forKey: .type)
        let createdAt = try container.decode(Date.self, forKey: .createdAt)
        let origin = try container.decode(Data.self, forKey: .origin)
        let url = try container.decode(URL.self, forKey: .url)
        //可选类型解码调用 decodeIfPresent
        let comment = try container.decodeIfPresent(String.self, forKey: .comment)
        //对内嵌meta做处理
            let meta = try container.nestedContainer(keyedBy: MetaCodingKeys.self, forKey: .meta)
            let duration = try meta.decode(Float.self, forKey: .duration)
            //如果需要对数组内容进行处理可以调用 nestedUnkeyedContainer
            var unkeyedContainer = try meta.nestedUnkeyedContainer(forKey: .slices)
            var percentages:[Float] = []
            while !unkeyedContainer.isAtEnd { //遍历到最后一个元素
                let sliceDuration = try unkeyedContainer.decode(Float.self)
                percentages.append(sliceDuration / duration)
            }
        
        self.init(accessToken: accessToken,
                  expiresIn: expiresIn,
                  remindIn: remindIn,
                  isRealName: isRealName,
                  uid: uid,
                  type: type,
                  createdAt: createdAt,
                  duration: duration,
                  origin: origin,
                  url: url,
                  comment: comment,
                  slices: percentages)
    }
    
    init(accessToken:String,
         expiresIn:Int32,
         remindIn:String,
         isRealName:String,
         uid:String,
         type:EpisodeType,
         createdAt:Date,
         duration:Float,
         origin:Data,
         url:URL,
         comment:String?,
         slices:[Float]) {
        self.accessToken = accessToken
        self.expiresIn = expiresIn
        self.remindIn = remindIn
        self.isRealName = isRealName
        self.uid = uid
        self.type = type
        self.createdAt = createdAt
        self.duration = duration
        self.origin = origin
        self.url = url
        self.comment = comment
        self.slices = slices
    }
    
}

//处理日期时间
extension EpisodeGeneral {
    //自定义编码 [由于方法可能会失败,可能抛出异常,throws]
    func encode(to encoder:Encoder) throws {
        //1.根据要编码的内容创建对应的容器,这里我们要编码成带有key和value的json
        var container = encoder.container(keyedBy: CodingKeys.self)
        //2.将内容编码到容器 [由于可能会失败,所以需要抛出异常,try]
        try container.encode(accessToken, forKey: .accessToken)
        try container.encode(expiresIn, forKey: .expiresIn)
        try container.encode(remindIn, forKey: .remindIn)
        try container.encode(isRealName, forKey: .isRealName)
        try container.encode(uid, forKey: .uid)
        try container.encode(createdAt, forKey: .createdAt)
        try container.encode(origin, forKey: .origin)
        try container.encode(url, forKey: .url)
        try container.encode(type, forKey: .type)
        try container.encode(comment, forKey: .comment)
        
        var meta = container.nestedContainer(keyedBy: MetaCodingKeys.self, forKey: .meta)
            try meta.encode(duration, forKey: .duration)
            //3.自定义数组编码容器
            var unkeyedContainer = meta.nestedUnkeyedContainer(forKey: .slices)
            try slices.forEach({ (element) in
                try unkeyedContainer.encode("\(element * 100)%")
            })
        
    }
    
}


